package org.penguin.boot.security.entity;

import lombok.*;
import lombok.experimental.Accessors;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.UpdateTimestamp;
import org.hibernate.validator.constraints.Length;
import org.penguin.boot.security.validation.annotation.ValidPassword;
import org.penguin.boot.security.validation.group.InsertGroup;
import org.penguin.boot.security.validation.group.UpdateGroup;

import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import java.io.Serial;
import java.io.Serializable;
import java.util.Collection;
import java.util.Date;

@Getter
@Setter
@ToString
@Entity
@DynamicUpdate
@NoArgsConstructor
@Accessors(chain = true)
@Table(name = "users", uniqueConstraints = {@UniqueConstraint(name = "unique_users_email", columnNames = {"email"})},
        indexes = {@Index(columnList = "fullName", name = "index_users_full_name")
        }) // name = "users",
@org.hibernate.annotations.Table(appliesTo = "users", comment = "用户表")
public class User implements Serializable {

    @Serial
    private static final long serialVersionUID = 2838446311247793653L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(columnDefinition = "BIGINT comment '用户ID'")
    @Null(message = "新增时，ID必须为空！", groups = {InsertGroup.class})
    @NotNull(message = "更新时，ID不能为空！", groups = UpdateGroup.class)
    private Long id;

    @Column(length = 50, columnDefinition = "VARCHAR(50) comment '姓名'")
    private String fullName;

    @Column(length = 50, columnDefinition = "VARCHAR(50) comment '昵称'")
    private String nickName;

    @Column(length = 64, columnDefinition = "VARCHAR(64) comment 'Email'")
    @NotBlank(message = "Email不能为空！")
    @Length(min = 10, max = 64, message = "Email最少10个字符，最多64个字符！")
    @Email(message = "请输入有效的Email地址！")
    private String email;

    @Column(length = 60, columnDefinition = "VARCHAR(60) comment '密码'")
    @NotBlank(message = "密码不能为空！")
    private String password;

    @Column(length = 64, columnDefinition = "VARCHAR(60) comment '盐值'")
    @NotBlank(message = "盐值不能为空！")
    private String salt;

    @Column(columnDefinition = "BIT(1) comment '用户是否可用'")
    private boolean enabled;

    @Column(columnDefinition = "BIT(1) comment 'token是否过期'")
    private boolean tokenExpired;

    @CreationTimestamp
    @Column(updatable = false, columnDefinition = "DATETIME comment '创建时间'")
    private Date createdAt;

    @UpdateTimestamp
    @Column(insertable = false, columnDefinition = "DATETIME comment '更新时间'")
    private Date updatedAt;

    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(
            name = "users_roles",
            joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
    @ToString.Exclude
    private Collection<Role> roles;
}